"use strict";

var $ = require("jquery");

var toolkit = require("./toolkit");
var Sudoku = require("./sudoku");

const tapEvent = "click";

let isMaked = false;

module.exports = {
    Buttons: require("./buttons"),
    toolkit: require("./toolkit"),

    ui: {},
    make(container, popupNumbers) {
        if (isMaked) {
            return;
        }
        isMaked = true;

        this.ui.container = $(container);
        this.ui.popupNumbers = $(popupNumbers).hide().removeClass("hidden");
        this.bindEvents();

        this.rebuild();
    },

    rebuild: function() {
        var puzzle = new Sudoku().generate().make();
        var rowClasses = ["r-top", "r-center", "r-bottom"];
        var colClasses = ["c-left", "c-center", "c-right"];

        var rows = puzzle.map(function(row, rowIndex) {
            return $("<div>")
                .addClass(rowClasses[rowIndex % 3])
                .append(row.map(function(v, colIndex) {
                    return $("<span>").text(v)
                        .addClass(v ? "fixed" : "empty")
                        .addClass(colClasses[colIndex % 3]);
                }));
        });
        this.ui.container.empty().append(rows);
        $(window).trigger("resize");
    },

    popupNumbers(target) {
        var $ui = this.ui.popupNumbers;
        var $target = $(target);
        this.targetCell = $target;
        var p = $target.position();

        const BLOCK_WIDTH = 48;
        const OFFSET = BLOCK_WIDTH + 2;
        const UI_WIDTH = BLOCK_WIDTH * 3 + 10;
        var left = Math.max(0, p.left - OFFSET);
        var top = Math.max(0, p.top - OFFSET);
        left = Math.min(left, $(window).width() - UI_WIDTH);

        $ui.css({
            left: `${left}px`,
            top: `${top}px`
        }).show();
    },

    check() {
        var data = this.ui.container.children().toArray().map(function(row) {
            return $(row).children().toArray().map(function(cell) {
                return ~~cell.innerText;
            });
        });

        var Checker = require("./checker");
        var c = Checker.check(data);
        var marks = c.marks;

        this.ui.container.children().each(function(rowIndex, row) {
            $(row).children().each(function(colIndex, cell) {
                if (cell.classList.contains("fixed")) {
                    return;
                }

                if (marks[rowIndex][colIndex]) {
                    $(cell).removeClass("error");
                } else {
                    $(cell).addClass("error");
                }
            });
        });

        return c.isSuccess;
    },

    bindEvents($container, $popupNumbers) {
        var ui = this.ui;
        var $container = ui.container;
        var $popupNumbers = ui.popupNumbers;
        var _this = this;

        $container.on(tapEvent, "span", function(e) {
            var cell = e.currentTarget;
            if (cell.classList.contains("fixed")) {
                return;
            }

            _this.popupNumbers(cell);
        });

        $popupNumbers.on(tapEvent, "span", (function() {
            function setValue(target, v) {
                target.text(v);
                if (v) {
                    target.removeClass("empty");
                } else {
                    target.addClass("empty");
                }
            }

            function mark(target, classes) {
                var mark = Array.prototype.filter.call(classes, function(c) {
                    return /^mark/.test(c);
                })[0];

                if (!mark) {
                    target.removeClass("mark1 mark2 error");
                    setValue(target, 0);
                } else {
                    var isClear = target.get(0).classList.contains(mark);
                    target.removeClass("mark1 mark2 error");
                    if (!isClear) {
                        target.addClass(mark);
                    }
                }
            }

            return function(e) {
                var cell = $(e.currentTarget);
                var target = $(_this.targetCell);

                if (cell.get(0).classList.contains("empty")) {
                    mark(target, cell.get(0).classList);
                } else {
                    setValue(target, cell.text() || 0);
                }

                $popupNumbers.hide();
            };
        })());

        $(window).on("resize", function() {
            var width = $("span:first", $container).width();
            $("span", $container)
                .height(width)
                .css("line-height", width + "px")
                .css("font-size", width < 32 ? width / 2 : "");
        });
    }
};
